''' <summary>
''' This is a game component that implements IUpdateable.
''' </summary>
Public Class ball
    Inherits Microsoft.Xna.Framework.DrawableGameComponent
    Private mBall As Model
    Private mScale As Vector3
    Private mRotate As Vector3
    Private mLocation As Vector3
    Private mJumping As Boolean = False
    Private mFalling As Boolean = False
    Private msngJumpVelocity As Single
    Private msngJumpValue As Single
    Private msngGravity As Single
    Private mStartLocation As Single
    Private mHeldLocation As Vector3
    Private mFallSpeed As Single
    Private mGameRun As GameRun

    Public Sub New(ByVal game As Game, ByRef GameRun As GameRun)
        MyBase.New(game)
        mGameRun = GameRun
        ' TODO: Construct any child components here
    End Sub
    Public ReadOnly Property IsJumping As Boolean
        Get
            Return mJumping
        End Get
    End Property
    Public ReadOnly Property IsFalling As Boolean
        Get
            Return mFalling
        End Get
    End Property
    Public Property Location As Vector3

        Get
            Return mLocation
        End Get
        Set(value As Vector3)
            mLocation = value
        End Set
    End Property
    Public Property Scale As Vector3

        Get
            Return mScale
        End Get
        Set(value As Vector3)
            mScale = value
        End Set
    End Property
    Public Property Rotation As Vector3

        Get
            Return mRotate
        End Get
        Set(value As Vector3)
            mRotate = value
        End Set
    End Property
    Public Property RotateX As Single
        Set(value As Single)
            mRotate.X = value Mod 360
        End Set
        Get
            Return mRotate.X
        End Get
    End Property
    Public Property RotateY As Single
        Set(value As Single)
            mRotate.Y = value Mod 360
        End Set
        Get
            Return mRotate.Y
        End Get
    End Property
    Public Property RotateZ As Single
        Set(value As Single)
            mRotate.Z = value Mod 360
        End Set
        Get
            Return mRotate.Z
        End Get
    End Property
    Public Property LocationX As Single
        Set(value As Single)
            mLocation.X = value
        End Set
        Get
            Return mLocation.X
        End Get
    End Property
    Public Property LocationY As Single
        Set(value As Single)
            mLocation.Y = value
        End Set
        Get
            Return mLocation.Y
        End Get
    End Property
    Public Property LocationZ As Single
        Set(value As Single)
            mLocation.Z = value
        End Set
        Get
            Return mLocation.Z
        End Get
    End Property
    ' Resets the objects World matracies to be what has been specified
    Private Sub ResetModel()
        Dim myMatrix As Matrix

        myMatrix = Matrix.Identity * Matrix.CreateScale(mScale) * Matrix.CreateRotationX(mRotate.X) * Matrix.CreateRotationY(mRotate.Y) * Matrix.CreateRotationZ(mRotate.Z) * Matrix.CreateTranslation(mLocation)
        For Each ModelMesh As ModelMesh In mBall.Meshes
            Dim transforms As Matrix() = New Matrix(mBall.Bones.Count) {}
            mBall.CopyAbsoluteBoneTransformsTo(transforms)
            For Each effect As BasicEffect In ModelMesh.Effects
                effect.View = mGameRun.Effect.View
                effect.Projection = mGameRun.Effect.Projection
                effect.World = myMatrix
                effect.EnableDefaultLighting()
            Next effect
        Next
    End Sub

    ''' <summary>
    ''' Allows the game component to perform any initialization it needs to before starting
    ''' to run.  This is where it can query for any required services and load content.
    ''' </summary>
    Public Overrides Sub Initialize()
        ' TODO: Add your initialization code here
        mScale = New Vector3(1, 1, 1)
        mRotate = New Vector3(0, 0, 0)
        mLocation = Vector3.Zero
        MyBase.Initialize()
    End Sub
    ' //////////////////////////////////////////////////////////////////////////////////////
    ' Load the sphere here.
    Protected Overrides Sub LoadContent()
        ' Load the sphere
        mBall = Game.Content.Load(Of Model)("sphere")
        MyBase.LoadContent()
    End Sub
    ' //////////////////////////////////////////////////////////////////////////////////////
    ' Draw the ball in it's location
    Public Overrides Sub Draw(gameTime As Microsoft.Xna.Framework.GameTime)
        ResetModel()
        For Each Model As ModelMesh In mBall.Meshes
            Model.Draw()
        Next
        MyBase.Draw(gameTime)
    End Sub
    ''' <summary>
    ''' Allows the game component to update itself.
    ''' </summary>
    ''' <param name="gameTime">Provides a snapshot of timing values.</param>
    Public Overrides Sub Update(ByVal gameTime As GameTime)
        If (mJumping) Then
            Me.LocationY += msngJumpVelocity
            msngJumpVelocity += msngGravity
            If (Me.LocationY <= mStartLocation) Then
                mJumping = False
                Me.LocationY = mStartLocation
            End If
        End If
        If (mFalling) Then
            Me.LocationZ += mFallSpeed
            If (Me.LocationZ > mStartLocation + mGameRun.UnitSize Or Me.LocationY < 0) Then
                Me.LocationY -= mFallSpeed
            End If
            If (Me.LocationY < 0) Then
                Me.LocationZ -= mFallSpeed
            End If
            If (Me.LocationY < -(mGameRun.UnitSize * 10) And mFallSpeed >= 0) Then
                mFallSpeed = -mFallSpeed
            End If
            If (Me.LocationY >= mHeldLocation.Y And mFallSpeed < 0) Then
                Me.Location = mHeldLocation
                mFalling = False
                Me.Jump()
            End If
        End If
        ' TODO: Add your update code here
        MyBase.Update(gameTime)
    End Sub
    ' ///////////////////////////////////////////////////////////////////////////////////////////
    ' Jump as required
    Public Sub Jump()
        If (Not mJumping And Not mFalling) Then
            mJumping = True
            msngJumpValue = CSng(mGameRun.UnitSize * 0.275)
            msngGravity = -CSng(mGameRun.UnitSize * 0.05)
            mStartLocation = Me.LocationY
            msngJumpVelocity = msngJumpValue
        End If
    End Sub
    ' ///////////////////////////////////////////////////////////////////////////////////////////
    ' Fall as required
    Public Sub Fall(ByVal Speed As Single)
        If (Not mFalling) Then
            mHeldLocation = Me.Location
            mFallSpeed = Speed
            mFalling = True
        End If
    End Sub
End Class
